package top.huntwolf.admin.service;

import org.apache.shiro.crypto.hash.SimpleHash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.huntwolf.admin.common.enums.CodeMsg;
import top.huntwolf.admin.common.enums.OrderStatus;
import top.huntwolf.admin.common.enums.OrderType;
import top.huntwolf.admin.dao.BookDao;
import top.huntwolf.admin.dao.OrderDao;
import top.huntwolf.admin.exception.ServiceException;
import top.huntwolf.admin.pojo.orderEntity.Order;
import top.huntwolf.admin.pojo.orderEntity.OrderBook;
import top.huntwolf.admin.pojo.PurchaseVo;
import top.huntwolf.admin.pojo.Trade;
import top.huntwolf.admin.pojo.book.Book;
import top.huntwolf.admin.pojo.shop.ShopContext;
import top.huntwolf.admin.utils.OrderUtil;
import top.huntwolf.admin.utils.RedisUtil;
import top.huntwolf.admin.utils.TokenUtil;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Transactional
public class OrderService {

    @Autowired
    private OrderDao orderDao;

    @Autowired
    private CartService cartService;

    @Autowired
    private BookDao bookDao;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private BookReserveService reserveService;

    @Autowired
    private AddressService addressService;

    /*删除订单*/
    public void deleteOrder(String order_id){
        int result = orderDao.delete(order_id);
        if (result == 0){
            throw new ServiceException(CodeMsg.ORDER_NOT_EXIST);
        }
    }

    
    /*创建购买订单*/
    public String generateTemporaryOrder(Order order){


        if(!order.getOrderStatus().equals(OrderStatus.WAIT_PAY)){
            throw new ServiceException(CodeMsg.ORDER_STATUS_ERROR);
        }
        order.setOrderType(OrderType.BUY);
        String orderId = OrderUtil.getOrderIdByUUID();
        order.setOrderId(orderId);
        order.setCreateTime(new Date());
        order.setOpenId(TokenUtil.getTokenOpenId());
        order.setAddress(addressService.selectById(order.getAddressId()));
        List<OrderBook> orderBooks = new ArrayList<>();
        for (OrderBook ob : order.getBooks()){
            ob.setOrderId(orderId);
            orderBooks.add(ob);
        }
        order.setBooks(orderBooks);
        order.setStoreId(ShopContext.get());

        //减少书本库存量
        reserveService.submitOrderReduceStorage(order.getBooks());

        //创建临时订单
        String key = "order-" + order.getOpenId() + "-" + order.getOrderId();
        redisUtil.set(key,"",10*60);
        redisUtil.set(key+"-0",order);

        //清空购物车中的书本
        cartService.ClearSubmit(order.getBooks());
        return orderId;
    }

    public void generateOrder(Order order){
        orderDao.insert(order);
        orderDao.saveOrderBook(order.getBooks());
    }

    public void generatePaymentOrder(String orderId,String openId){

        String key = "order-" + openId + "-" + orderId;

        Order order = (Order) redisUtil.get(key + "-0");
        if (order==null){
            order = orderDao.selectOrderById(orderId);
        }
        order.setPayTime(new Date());
        if(order.getOrderStatus().equals(OrderStatus.WAIT_PAY)||order.getOrderStatus().equals(OrderStatus.INCOMPLETE)){
            order.setOrderStatus(OrderStatus.WAIT_DELIVER);
        }else {
            throw new ServiceException(CodeMsg.ORDER_STATUS_ERROR);
        }
        generateOrder(order);
        redisUtil.del(key,key + "-0");
    }

    public void generateCancelOrder(String orderId){
        String key = "order-" + TokenUtil.getTokenOpenId() + "-" + orderId;
        Order order = (Order) redisUtil.get(key + "-0");
        if(order == null){
            throw new ServiceException(CodeMsg.ORDER_CANCEL_FAIL);
        }
        if(order.getOrderStatus().equals(OrderStatus.WAIT_PAY)){
            order.setOrderStatus(OrderStatus.CANCELED);
        }else {
            throw new ServiceException(CodeMsg.ORDER_STATUS_ERROR);
        }
        reserveService.cancelOrderIncreaseStorage(order.getBooks());
        generateOrder(order);
        redisUtil.del(key,key + "-0");

    }

    public void generateIncomplete(String key){
        Order order = (Order) redisUtil.get(key + "-0");
        if(order.getOrderStatus().equals(OrderStatus.WAIT_PAY)){
            order.setOrderStatus(OrderStatus.INCOMPLETE);
        }else {
            throw new ServiceException(CodeMsg.ORDER_STATUS_ERROR);
        }
        generateOrder(order);
        redisUtil.del(key,key + "-0");
    }

    public void refundOrder(Order order){
        if (!orderDao.selectOrderById(order.getOrderId()).getOrderStatus().equals(OrderStatus.WAIT_PAY)){
            order.setOrderStatus(OrderStatus.REFUND_PROCESS);
        }else {
            throw new ServiceException(CodeMsg.ORDER_STATUS_ERROR);
        }
        orderDao.update(order);
    }

    public Order queryBooksInOrder(String orderId){
        Order order = orderDao.selectBuyBooksInOrder(orderId);

        if (order == null){
            order = (Order) redisUtil.get("order-" + TokenUtil.getTokenOpenId() + "-" + orderId + "-0");
            order.setTime(redisUtil.getExpire("order-" + TokenUtil.getTokenOpenId() + "-" + orderId));
            order.setOpenId(null);
        }
        if (order == null){
            throw new ServiceException(CodeMsg.ORDER_NOT_EXIST);
        }
        return order;
    }

    public Order queryStoreByOrder(String orderId,String openId){
        Order order = orderDao.selectOrderById(orderId);

        if (order == null){
            order = (Order) redisUtil.get("order-" + openId + "-" + orderId + "-0");
            order.setTime(redisUtil.getExpire("order-" + openId + "-" + orderId));
        }
        if (order == null){
            throw new ServiceException(CodeMsg.ORDER_NOT_EXIST);
        }
        return order;
    }

    public List<Order> queryBuyOrdersByUser(){
        String openId = TokenUtil.getTokenOpenId();
        List<Order> orders = orderDao.selectBuyOrderByUser(openId, OrderType.BUY.toValue().toString());
        Set<String> keys = redisUtil.keys("order-" + openId + "-*");
        List<Order> orderList = new ArrayList<>();
        for (String key:keys){
            if (key.endsWith("-0")){
                Order order = (Order) redisUtil.get(key);
                order.setTime(redisUtil.getExpire(key.substring(0,key.length()-2)));
                order.setOpenId(null);
                orderList.add(0,order);
            }
        }
        orderList.stream().sorted(Comparator.comparing(Order::getTime).reversed()).collect(Collectors.toList());
        orders.addAll(0,orderList);
        return orders;
    }

    public void updateOrder(Order order){

        orderDao.update(order);

    }

    public List<Book> searchBuyBooksAllOrderNumLastMonth(){

        List<Order> orders = orderDao.selectBuyBooksAllOrderNumLastMonth();
        List<Book> books = new ArrayList<>();
        for(Order order : orders) {
            books.add(bookDao.selectBookByISBN(order.getBooks().get(0).getIsbn()));
        }

        return books;
    }

    public Trade searchBuyBookByIsbnTransaction(String isbn){
        Trade trade = orderDao.selectBuyBookTransaction(isbn);
        if (trade.getAvatar() == null){
            return trade;
        }
        trade.setAvatars(trade.getAvatar().split(","));
        trade.setNicknames(trade.getNickname().split(","));
        trade.setAvatar(null);
        trade.setNickname(null);
        return trade;
    }

    public List<PurchaseVo> searchRecentBuyBook(){
        return orderDao.selectRecentBuyBook();
    }
}
